#
# Realise par Thomas Moreau et Nicolas Berrez
#  - Jonction entre partie metier et partie web : Thomas Moreau et Nicolas Berrez
#  - Serveur HTTP, Web Sockets avec Channel : Thomas Moreau
#
from framework.bottle import request, route, jinja2_view as view, redirect, default_app, static_file
from game.GameUpdater import GameUpdater
from game.SnakeWord import SnakeWord
from game.User import User
from google.appengine.api import users
from google.appengine.ext.webapp.util import run_wsgi_app
from game.Dico import Dico
import logging
import time
from google.appengine.api import channel
from google.appengine.ext import db
from random import random, randint

listeGame = {}        
dicoFr = Dico("static/resources/dicofr.txt")
dicoEn = Dico("static/resources/dict_vo")


class Game(db.Model):
     """All the data we store for a game"""
     #db.ReferenceProperty(listeGame)

    
@route('/room', method='GET')
@view('./views/room.tpl')
def room():
    check_user('/room')
    games = list()
    for jeu in listeGame:
        if not listeGame[jeu].isComplete() and not listeGame[jeu].isPrivate:
            games.append([listeGame[jeu].gameName, listeGame[jeu].userCreateur.pseudo, len(listeGame[jeu].playerList), listeGame[jeu].maxNbJoueur, listeGame[jeu].gameId])
    gamesPaused = list()
    for jeu in listeGame:
        for user in listeGame[jeu].playerList:
            if user.userId ==  users.get_current_user().user_id():
                gamesPaused.append([listeGame[jeu].gameName, listeGame[jeu].userCreateur.pseudo, len(listeGame[jeu].playerList), listeGame[jeu].maxNbJoueur, listeGame[jeu].gameId])
                
    
    #cree le token pour la connexion web socket
    token = channel.create_channel("room-socket")
    return {
            'title' : 'Salle de jeux',
            'name' : users.get_current_user().nickname(),
            'games' : games,
            'token' : token,
            'gamesPaused' : gamesPaused
            }

@route('/', method='GET')
def index():
    check_user('/')
    logging.info("coincoin")
    redirect('/room')

@route('/newgame', method='GET')
@view('./views/newgame.tpl')
def newgame():
    check_user('/newgame')
    return {
            'title' : 'Creer une nouvelle partie',
            'name' : users.get_current_user().nickname()
            }

@route('/newgame', method='POST')
def newgame_post():
    check_user('/newgame')
    game_id = str(int(time.time()) * 42) + users.get_current_user().user_id()
    game_name = request.forms.get('gamename')
    pseudo = request.forms.get('pseudo')
    privacy=False
    if request.forms.get('privacy')=="private":
        privacy = True
    
    nbplayers = request.forms.get('nbplayers')
    nbrows = request.forms.get('nbrows')
    nbcolumns = request.forms.get('nbcolumns')
    user = User(pseudo, "", users.get_current_user().user_id(),0)
    
    monDico = dicoEn
    if request.forms.get("lang") == "fr" : 
        monDico = dicoFr
    sn = SnakeWord(int(nbrows), int(nbcolumns), user, int(nbplayers), str(game_id), monDico, game_name,privacy)
    
    sn.addPlayeur(user)
    
    addGame(game_id, sn)
    
    #notifie les internautes dans la salle de jeu du nouveau jeu
    channel.send_message("room-socket", '{"refresh": "refresh"}')
    #redirige vers le jeu qui vient d'etre cree, en attente de joueurs
    redirect('/game/' + game_id)

@route('/game/:game_id', method='GET')
@view('./views/game.tpl')
def game(game_id):
    #TODO : g/game?id=game_id non ?
    check_user('/game/'+game_id)
    jeu = listeGame[game_id]
    sessionUser = users.get_current_user()
    #logging.info("nouveau joueur dans la partie ")
    
    user = None
    found = False
    for usr in jeu.playerList :
        if usr.userId == sessionUser.user_id() :
            found = True
            user = usr
    
    if not found :
        user = User("", sessionUser.email(), sessionUser.user_id(), 0)
        nb = jeu.addPlayeur(user)
        user.numero = nb
        #notifie les internautes dans la salle de jeu que le joueur a rejoint le jeu
        channel.send_message("room-socket", '{"refresh": "refresh"}')
    
    #logging.info("verif nb bien associe : " + user.numero)
    matrix = jeu.matrix.mat
    #TODO gerer le refresh de la page et l'actualisation des score correctement
    
    token = channel.create_channel(game_id + user.userId)
    scores = list()
    for u in jeu.playerList:
        scores.append(u.score)
            
    if jeu.isComplete():
        gu = GameUpdater(jeu)
        gu.send_update("ready_to_play", "", "", "", "", "","")
    

    return {
            'title' : 'Partie : ' + jeu.gameName,
            'name' : users.get_current_user().nickname(),
            'gamename' : jeu.gameName,
            'game_key' : game_id,
            'me' : user.userId,
            'number' :  user.numero,
            'channelId' : game_id + user.userId,
            'currentPlayer' : jeu.currentUserIndex,
            'ready' : jeu.isComplete(),
            'token' : token,
            'nbPlayers': jeu.maxNbJoueur,
            'scores': scores,
            'matrice': matrix,
            'random': randint(1, 20),
            'mots' : jeu.wordEntered
            }


@route('/game/:game_id/joue', method='POST')
def jouer_post(game_id):
    
    jeu = getGame(game_id)
    gu = GameUpdater(jeu)
        
    res = jeu.addWord(request.forms["ligne"],request.forms["colonne"],request.forms["lettre"],request.forms["mot"])
    
    if res == True : 
        jeu.nbPasser = 0;
        if jeu.isFinished() : 
            gu.send_update("game_over", "","", "", "", str(jeu.getWinner()),request.forms["mot"])
        else :
            gu.send_update("update_game", request.forms["ligne"], request.forms["colonne"], request.forms["lettre"], "", "",request.forms["mot"])
    else :
        gu.send_update("error", request.forms["ligne"], request.forms["colonne"], request.forms["lettre"], res, "","") 
    #gu.send_update(request.forms.get("ligne"), request.forms.get("colonne"), request.forms.get("lettre"), erreur, winner)
    #redirect('/game/' + game_id)
    
    
@route('/game/:game_id/passe', method='POST')
def passe_post(game_id):

    jeu = getGame(game_id)
    gu = GameUpdater(jeu)
    jeu.nbPasser +=1
    
    if jeu.nbPasser == jeu.maxNbJoueur : 
        removeGame(game_id)
        gu.send_update("game_over", "","", "", "", str(jeu.getWinner()))
    else :
        jeu.nextUser()
        gu.send_update("passe", "","", "", "", "")
        
@route('/static/<path:path>')
def static(path):
    return static_file(path, root='static/')

def check_user(uri):
    user = users.get_current_user()
    if not user:
        redirect(users.create_login_url(uri))



def getGame(game_id):
    return listeGame[game_id]

def removeGame(game_id):
    listeGame.pop(game_id)
    
def addGame(game_id, game):
    listeGame[game_id] = game

def main():
    run_wsgi_app(default_app())

if __name__ == "__main__":
    main()
